package cn.uc.ucgc.community.upgrade.api;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.uc.ucgc.community.upgrade.AppFiles;
import cn.uc.ucgc.community.upgrade.Constants;
import cn.uc.ucgc.community.upgrade.Task;
import cn.uc.ucgc.community.upgrade.Utils;

/**
 * 所有对外的java接口扩展，任务执行调度
 * 业务可以不实现，默认为空
 * @author yuyj@ucweb.com
 * @createDate 2014-1-3
 *
 */
public final class ApiImplMgr {
    private static final Logger logger = LoggerFactory.getLogger(ApiImplMgr.class);
    private static final int TASK_UNKOWN_TYPE = -1;
    private static final int TASK_PREPARE_TYPE = 1;
    private static final int TASK_EXE_TYPE = TASK_PREPARE_TYPE + 1;
    private static final int TASK_REVISE_TYPE = TASK_PREPARE_TYPE + 2;

    private static ApiImplMgr instance = new ApiImplMgr();
    private Task prepareTask;
    private Task exeTask;
    private Task reviseTask;

    private ApiImplMgr() {
    }

    public static ApiImplMgr getInstance() {
        return instance;
    }

    /**
     * 根据配置文件路径，初始化任务队列
     * @throws MalformedURLException
     */
    public void initTask() throws MalformedURLException {
        //首先获取对应的扩展库文件
        File file = new File(AppFiles.confHomeFile, "lib");
        if (!file.exists()) {
            logger.error("{} not exist", file.getAbsolutePath());
            return;
        }
        //加载该目录下的class文件（jar包及class文件）
        List<String> allClses = new ArrayList<String>();
        List<URL> needLoadCls = Utils.getClassFiles(file, allClses);
        if (needLoadCls.isEmpty()) {
            logger.warn("no ext IUpgradeJob to to");
            return;
        }

        //解析对应的任务，
        URLClassLoader clsLoader = new URLClassLoader(needLoadCls.toArray(new URL[0]));
        List<IUpgradeJob> jobLst = new ArrayList<IUpgradeJob>();
        for (String clsName : allClses) {
            try {
                Class<?> cls = clsLoader.loadClass(clsName);
                Object obj = cls.newInstance();
                if (obj instanceof IUpgradeJob) {
                    IUpgradeJob job = (IUpgradeJob) obj;
                    jobLst.add(job);
                }
            } catch (Exception e) {
                logger.error("", e);
            }
        }
        //检查是否有任务，如果有就初始化对应的Task
        if (jobLst.isEmpty()) {
            logger.warn("no ext IUpgradeJob to to");
            return;
        }
        //先做排序
        Collections.sort(jobLst, new Comparator<IUpgradeJob>() {
            @Override
            public int compare(IUpgradeJob o1, IUpgradeJob o2) {
                int firstVal = o1.getPriority();
                if (firstVal < 0 || firstVal > Integer.MAX_VALUE) {
                    firstVal = 10000;
                }
                int secondVal = o2.getPriority();
                if (secondVal < 0 || secondVal > Integer.MAX_VALUE) {
                    secondVal = 10000;
                }
                return firstVal - secondVal;
            }
        });
        prepareTask = new ApiTask(jobLst, TASK_PREPARE_TYPE);
        exeTask = new ApiTask(jobLst, TASK_EXE_TYPE);
        reviseTask = new ApiTask(jobLst, TASK_REVISE_TYPE);
    }

    public Task getPrepareTask() {
        return prepareTask;
    }

    public Task getExeTask() {
        return exeTask;
    }

    public Task getReviseTask() {
        return reviseTask;
    }

    /**
     * 将外部扩展任务转换为内部识别的任务
     * 
     * @author yuyj@ucweb.com
     * @createDate 2014-1-3
     *
     */
    class ApiTask extends Task {
        /*按配置顺序执行*/
        private List<IUpgradeJob> jobLst;
        private int type = TASK_UNKOWN_TYPE;

        public ApiTask(List<IUpgradeJob> jobs, int type) {
            super.setTaskDesc("Api Ext Task");
            this.jobLst = jobs;
            this.type = type;
        }

        @Override
        public void doTask(StringBuilder sb) throws Exception {
            switch (type) {
            case TASK_PREPARE_TYPE:
                logger.warn("do prepare Api :{}", jobLst.size());
                //任务执行中如果抛异常，则直接中断任务
                for (IUpgradeJob job : jobLst) {
                    job.doPrepareTask(AppFiles.oldVerHomeFile, AppFiles.newVerHomeFile, logger);
                }
                break;
            case TASK_EXE_TYPE:
                logger.warn("do exe Api :{}", jobLst.size());
                //任务执行中如果抛异常，则直接中断任务
                for (IUpgradeJob job : jobLst) {
                    job.doExeTask(AppFiles.oldVerHomeFile, AppFiles.newVerHomeFile, logger);
                }
                break;
            case TASK_REVISE_TYPE:
                logger.warn("do revise Api :{}", jobLst.size());
                for (IUpgradeJob job : jobLst) {
                    job.doPrepareTask(AppFiles.oldVerHomeFile, AppFiles.newVerHomeFile, logger);
                }
                break;
            default:
                sb.append(Constants.TASK_RESULT_NOTASK_SUFFIX);
                logger.warn("unkown this type");
                break;
            }
        }
    }
}
